package com.open.demo.span;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.text.style.ReplacementSpan;
import android.util.Log;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class FontAnimReplacementSpan extends ReplacementSpan {

    public static final String ALPHA = "Alpha";

    public static class TxtParam {
        public int start, end;
        public CharSequence text;
        public float x, y, centerY;
    }

    TextView tv;

    FontAnimReplacementSpan(TextView tv) {
        this.tv = tv;
    }

    private static Paint staticPaint = new Paint();
    private Matrix matrix = new Matrix();

    private float scaleX = 1.0f;
    private float scaleY = 1.0f;
    private float rotate = 0;
    private float translateX = 0;
    private float translateY = 0;
    private int color = Color.BLACK;

    @Override
    public void draw(@NonNull final Canvas canvas, final CharSequence text, final int start, final int end,
            final float x, final int top, final int y,
            final int bottom, @NonNull final Paint paint) {
        paint.getFontMetricsInt(paintMetrics);
        TxtParam textParam = new TxtParam();
        staticPaint.set(paint);
        //
        RectF rect = new RectF();
        int width = measureWidth(paint, text, start, end);
        rect.set(x, y + fontMetrics.ascent, width + x, y + fontMetrics.descent);
        textParam.x = rect.left;
        textParam.y = rect.centerY() - (paintMetrics.descent + paintMetrics.ascent) / 2f;
        //
        canvas.save();
        //
        matrix.reset();
        // 旋转
        matrix.setRotate(rotate, rect.centerX(), rect.centerY());
        // 缩放
        matrix.postScale(scaleX, scaleY, rect.centerX(), rect.centerY());
        // 位移
        matrix.postTranslate(translateX, translateY);
        canvas.concat(matrix);
        // 透明度(FIXME:无效，需要排查下原因)
        staticPaint.setAlpha(alpha);
        // 颜色
        staticPaint.setColor(color);
        // 字库
        if (null != mTypeface) {
            staticPaint.setTypeface(mTypeface);
        }
        // 绘制文本内容
        Log.d("hailong.qiu", "span draw start:"+ start + " end:" + end);
        canvas.drawText(text, start, end, textParam.x, textParam.y, staticPaint);
        //
        canvas.restore();
    }

    public Typeface mTypeface;

    int alpha = 255;

    public void setAlpha(float value) {
        this.alpha = (int) (255 * (0.0f + value * (1.0f - 0.0f)));
//        this.alpha = (int) (255 * (value + value * (1.0f - value)));
        Log.d("hailong.qiu", "setAlpha value:" + value + " alpha:" + this.alpha);
        tv.invalidate();
    }

    public void setColor(int color) {
        this.color = color;
        tv.invalidate();
    }

    public void setScaleX(float scaleX) {
        this.scaleX = scaleX;
        tv.invalidate();
    }

    public void setScaleY(float scaleY) {
        this.scaleY = scaleY;
        tv.invalidate();
    }

    public void setTranslateX(float translateX) {
        this.translateX = translateX;
        tv.invalidate();
    }

    public void setTranslateY(float translateY) {
        this.translateY = translateY;
        tv.invalidate();
    }

    public void setRotate(float rotate) {
        this.rotate = rotate;
        tv.invalidate();
    }

    public int getAlpha() {
        return alpha;
    }

    private FontMetricsInt fontMetrics = new FontMetricsInt();
    private FontMetricsInt paintMetrics = new FontMetricsInt();

    @Override
    public int getSize(@NonNull final Paint paint, final CharSequence text, final int start, final int end,
            @Nullable final FontMetricsInt fm) {
        if (fm != null) {
            FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
            fm.ascent = fontMetricsInt.ascent;
            fm.descent = fontMetricsInt.descent;
            fm.top = fontMetricsInt.top;
            fm.bottom = fontMetricsInt.bottom;
            fontMetrics.ascent = fm.ascent;
            fontMetrics.descent = fm.descent;
            fontMetrics.top = fm.top;
            fontMetrics.bottom = fm.bottom;
        }
        int width = measureWidth(paint, text, start, end);
        return width;
    }

    private int measureWidth(Paint paint, CharSequence text, int start, int end) {
        return (int) paint.measureText(text, start, end);
    }

}
